/**
 * 
 */
package org.t2.backstage.module.player.service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.banish.sql.core.dao.Dao;
import org.banish.sql.core.datasource.IDataSource;
import org.banish.sql.core.util.QuerySet;
import org.gaming.ruler.schedule.LoopingTask;
import org.gaming.service.service.AbstractService;
import org.gaming.tool.DateTimeUtil;
import org.gaming.tool.ListMapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.t2.backstage.module.gameserver.model.GameServer;
import org.t2.backstage.module.gameserver.service.DataBaseManager;
import org.t2.backstage.module.gameserver.service.GameServerService;
import org.t2.backstage.module.player.model.PlayerPayInServer;
import org.t2.backstage.module.player.struct.CreateGroupByBorn;
import org.t2.backstage.module.player.struct.RechargeGroupByBorn;
import org.t2.backstage.module.player.vo.PlayerPayResume;
import org.t2.backstage.module.system.model.SystemCounter;
import org.t2.backstage.module.system.service.SystemCounterService;

/**
 * 
 */
@Service
public class PlayerPayInServerService extends AbstractService<PlayerPayInServer> {

	@Autowired
	private DataBaseManager dataBaseManager;
	@Autowired
	private GameServerService gameServerService;
	@Autowired
	private SystemCounterService systemCounterService;
	
	@LoopingTask(name = "PlayerTimer-游戏服充值", spaceTime = DateTimeUtil.ONE_SECOND_MILLIS * 10, execGroup = 4)
	private void runInSchedule() {
		SystemCounter systemCounter = systemCounterService.instance();
		if(DateTimeUtil.currMillis() < systemCounter.getPayInServerTime()) {
			return;
		}
		systemCounter.setPayInServerTime(DateTimeUtil.tomorrowZeroMillis());
		systemCounterService.update(systemCounter);
		
		countServerRecharge();
	}
	
	public void countServerRecharge() {
		for(GameServer gameServer : gameServerService.getEntityList(0)) {
			countServerRecharge(gameServer);
		}
	}
	
	/**
	 * 统计某个服务器下以渠道、创号日期进行分组的充值情况
	 * @param gameServer
	 */
	public void countServerRecharge(GameServer gameServer) {
		IDataSource dataBase = dataBaseManager.getLogDb(gameServer.getId());
		if(dataBase == null) {
			return;
		}
		logger.info("统计游戏服{}-{}下的充值情况", gameServer.getId(), gameServer.getName());
		
		String sql = "SELECT "
				+ "channel_id AS channelId, "
				+ "born_date AS bornDate, "
				+ "sum(money) AS money, "
				+ "count(DISTINCT player_id) AS playerCount "
				+ "FROM player_recharge_log GROUP BY channel_id, born_date";
		List<RechargeGroupByBorn> logs = Dao.queryAliasObjects(dataBase, RechargeGroupByBorn.class, sql);
		Map<String, RechargeGroupByBorn> rechargeMap = ListMapUtil.listToMap(logs, RechargeGroupByBorn::getKey);
		
		String playerCreateSql = "SELECT "
				+ "channel_id AS channelId, "
				+ "born_date AS bornDate, "
				+ "count(1) AS playerCount "
				+ "FROM player_create_log GROUP BY channel_id, born_date";
		List<CreateGroupByBorn> createLogs = Dao.queryAliasObjects(dataBase, CreateGroupByBorn.class, playerCreateSql);
		
		List<PlayerPayInServer> insertList = new ArrayList<>();
		for(CreateGroupByBorn log : createLogs) {
			PlayerPayInServer data = new PlayerPayInServer();
			data.setServerUid(gameServer.getId());
			data.setChannelId(log.getChannelId());
			data.setBorn(log.getBornDate());
			RechargeGroupByBorn recharge = rechargeMap.get(log.getKey());
			if(recharge != null) {
				data.setMoney(recharge.getMoney());
				data.setPayCount(recharge.getPlayerCount());
			}
			data.setPlayerCount(log.getPlayerCount());
			insertList.add(data);
		}
		this.repository().getBaseDao().insertUpdate(insertList);
	}
	
	
	public Map<Integer, Map<Long, List<PlayerPayInServer>>> payInServers(List<Integer> channelIds, List<Integer> serverUids) {
		QuerySet querySet = new QuerySet();
		//渠道选择
		if(channelIds != null && !channelIds.isEmpty()) {
			querySet.findInSet("channel_id", channelIds);
		}
		//服务器选择
		if(serverUids != null && !serverUids.isEmpty()) {
			querySet.findInSet("server_uid", serverUids);
		}
		querySet.formWhere();
		List<PlayerPayInServer> playerPayInServers = repository().getBaseDao().queryListWhere(querySet.getWhere(), querySet.getParams());
		return ListMapUtil.fillTwoListMap(playerPayInServers, PlayerPayInServer::getBorn, PlayerPayInServer::getChannelId);
	}
	
	/**
	 * 填充充值信息
	 * @param channelIds
	 * @param serverUids
	 * @param resumeVos
	 */
	public void fillPayInfo(List<Integer> channelIds, List<Integer> serverUids, Collection<? extends PlayerPayResume> resumeVos) {
		//设置充值总额、付费率信息
		Map<Integer, Map<Long, List<PlayerPayInServer>>> payBornChannelMap = this.payInServers(channelIds, serverUids);
		for(PlayerPayResume resuetVo : resumeVos) {
			Map<Long, List<PlayerPayInServer>> channelMap = payBornChannelMap.get(resuetVo.getBornDate());
			if(channelMap == null) {
				continue;
			}
			List<PlayerPayInServer> list = channelMap.get(resuetVo.getChannelId());
			if(list == null) {
				continue;
			}
			long rechargeTotal = 0;
			int payCount = 0;
			int playerCount = 0;
			for(PlayerPayInServer pay : list) {
				rechargeTotal += pay.getMoney();
				payCount += pay.getPayCount();
				playerCount += pay.getPlayerCount();
			}
			resuetVo.setRechargeTotal(rechargeTotal / 100);
			resuetVo.setPayPlayerCount(payCount);
			resuetVo.setPlayerCount(playerCount);
			if(resuetVo.getPlayerCount() > 0) {
				float floatRate = resuetVo.getPayPlayerCount() * 1.0f / resuetVo.getPlayerCount() * 100;
				BigDecimal payRate = new BigDecimal("" + floatRate).setScale(2, RoundingMode.UP);
				resuetVo.setPayRate(payRate.toString() + "%");
			}
		}
	}

	@Override
	public void mergeServer(int mergeDbZoneId) {
		//不用实现
	}
}
